package com.ymx.darling.util;

import com.ymx.darling.bean.sql.SqlStatement;
import com.ymx.darling.dialect.DialectManager;
import com.ymx.darling.wrapper.QueryWrapper;
import com.ymx.darling.wrapper.Wrappers;
import com.ymx.darling.wrapper.fragment.WhereSegment;
import com.ymx.darling.wrapper.fragment.lambda.LambdaGetter;
import com.ymx.darling.wrapper.fragment.lambda.WhereLambda;

/**
 * 常用过函数封装
 * @author 爱Java的小于
 */
public class FUN {
    //-------------------------快速构建QueryWrapper---------------------------
    public static QueryWrapper select(String... columns) {
        return Wrappers.query().select(columns);
    }

    @SafeVarargs
    public static <T> QueryWrapper select(LambdaGetter<T>... getter) {
        return Wrappers.query().select(getter);
    }

    public static QueryWrapper select(String[]... columns) {
        return Wrappers.query().select(columns);
    }

    public static QueryWrapper select(String[] columns, String... cols) {
        return Wrappers.query().select(columns, cols);
    }

    public static QueryWrapper selectAs(String column, String asName) {
        return Wrappers.query().selectAs(column, asName);
    }

    public <L> QueryWrapper selectAs(LambdaGetter<L> column, String asName) {
        return Wrappers.query().selectAs(column, asName);
    }

    public QueryWrapper selectAs(QueryWrapper columnWrapper, String asName) {
        return Wrappers.query().selectAs(columnWrapper, asName);
    }

    public QueryWrapper selectDistinct() {
        return Wrappers.query().selectDistinct();
    }

    public QueryWrapper selectSegment(String template, Object... params) {
        return Wrappers.query().selectSegment(template, params);
    }


    //------------------------- 通用函数-----------------------------------
    public static String MAX(String column) {
        return "MAX("+column+")";
    }
    public static String MIN(String column) {
        return "MIN("+column+")";
    }
    public static String COUNT(String column) {
        return "COUNT("+column+")";
    }
    public static String AVG(String column) {
        return "AVG("+column+")";
    }
    public static String SUM(String column) {
        return "SUM("+column+")";
    }
    public static String AS(String column, String asName) {
        return column + " AS " + asName;
    }
    public static String ABS(String column) {
        return "ABS("+column+")";
    }
    public static String SUBSTRING(String column, int start, int length) {
        return DialectManager.getDialect().subString(column, start, length);
    }
    public static String UPPER(String column) {
        return "UPPER("+column+")";
    }
    public static String LOWER(String column) {
        return "LOWER("+column+")";
    }
    public static String FLOOR(String column) {
        return "FLOOR("+column+")";
    }
    public static String CURRENT_DATE() {
        return DialectManager.getDialect().currentDate();
    }
    public static String CURRENT_TIMESTAMP() {
        return DialectManager.getDialect().currentTimestamp();
    }
    public static String CURRENT_TIME() {
        return DialectManager.getDialect().currentTime();
    }
    public static String CHAR_LENGTH(String column) {
        return DialectManager.getDialect().charLength(column);
    }


    public static <L> String MAX(LambdaGetter<L> column) {
        return MAX(LambdaUtil.getColumnName(column));
    }
    public static <L> String MIN(LambdaGetter<L> column) {
        return MIN(LambdaUtil.getColumnName(column));
    }
    public static <L> String COUNT(LambdaGetter<L> column) {
        return COUNT(LambdaUtil.getColumnName(column));
    }
    public static <L> String AVG(LambdaGetter<L> column) {
        return AVG(LambdaUtil.getColumnName(column));
    }
    public static <L> String SUM(LambdaGetter<L> column) {
        return SUM(LambdaUtil.getColumnName(column));
    }
    public static <L> String ABS(LambdaGetter<L> column) {
        return ABS(LambdaUtil.getColumnName(column));
    }
    public static <L> String AS(LambdaGetter<L> column, String asName) {
        return AS(LambdaUtil.getColumnName(column), asName);
    }
    public static <L> String SUBSTRING(LambdaGetter<L> column, int start, int length) {
        return SUBSTRING(LambdaUtil.getColumnName(column), start, length);
    }
    public static <L> String UPPER(LambdaGetter<L> column) {
        return UPPER(LambdaUtil.getColumnName(column));
    }
    public static <L> String LOWER(LambdaGetter<L> column) {
        return LOWER(LambdaUtil.getColumnName(column));
    }
    public static <L> String FLOOR(LambdaGetter<L> column) {
        return FLOOR(LambdaUtil.getColumnName(column));
    }
    public static <L> String CHAR_LENGTH(LambdaGetter<L> column) {
        return CHAR_LENGTH(LambdaUtil.getColumnName(column));
    }

    public static String IF(WhereLambda condition, Object valIfTrue, Object valIfFalse) {
        WhereSegment columnCondition = condition.subWhere(new WhereSegment());
        String conditionString = columnCondition.getSqlStatement().toString();
        return DialectManager.getDialect()._if(conditionString, valIfTrue, valIfFalse);
    }
    public static <T,F> String IF(WhereLambda condition, LambdaGetter<T> trueColumn, LambdaGetter<F> falseColumn) {
        return IF(condition, LambdaUtil.getColumnName(trueColumn), LambdaUtil.getColumnName(falseColumn));
    }
    public static Case CASE() {
        return new Case();
    }
    public static Case CASE(String column) {
        return new Case(column);
    }
    public static <T> Case CASE(LambdaGetter<T> lambdaGetter) {
        return new Case(lambdaGetter);
    }
    public static class Case {
        private final StringLink caseBuilder = new StringLink("CASE ");
        private final String WHEN = " WHEN ";
        private final String THEN = " THEN ";
        private final String ELSE = " ELSE ";
        private final String END = " END";

        public Case() {}

        public Case(String column) {
            caseBuilder.append(column);
        }

        public <T> Case(LambdaGetter<T> column) {
             this(LambdaUtil.getColumnName(column));
        }

        public Case WHEN(WhereLambda condition) {
            WhereSegment whereSegment = condition.subWhere(new WhereSegment());
            SqlStatement statement = whereSegment.getSqlStatement();
            caseBuilder.append(WHEN).append(statement.toString());
            return this;
        }

        public Case WHEN(String column) {
            caseBuilder.append(WHEN).append(column);
            return this;
        }

        public Case THEN(Object value) {
            caseBuilder.append(THEN).append(value);
            return this;
        }

        public Case ELSE(Object value) {
            caseBuilder.append(ELSE).append(value);
            return this;
        }

        public String END() {
            this.caseBuilder.append(this.END);
            return this.caseBuilder.toString();
        }

        public String END(String asName) {
            return AS(String.format("(%s)", this.END()), asName);
        }
    }
}
